#include "CFont.h"
#include "CImage.h"
#include "CFrame.h"
#include "CCore.h"
#include "CVideoManager.h"
#include "CLayer.h"
#include <stdarg.h>

//----------------------------------------------------------------------------
// Nome: CFont(void)
// Desc: desfault constructor
// Pams: nenhum
//----------------------------------------------------------------------------
CFont::CFont(void)
{
    bVisible        = true;
	sCurrentAnim	= -1;
	pr_Core         = NULL;
	pr_Layer        = NULL;
	pr_Image		= NULL;
	p_Font          = new FontStruct;
	p_fontBuffer    = new CImage();
	strTextBuffer;
}

//----------------------------------------------------------------------------
// Nome: ~CFont(void)
// Desc: destrutor padrão
// Pams: nenhum
//----------------------------------------------------------------------------
CFont::~CFont(void)
{
    Release();
}

//----------------------------------------------------------------------------
// Nome: Release(void)
// Desc: finaliza o Font
// Pams: nenhum
//----------------------------------------------------------------------------
bool CFont::Release(void)
{
	if(pr_Core)
	{
		if(pr_Image)
		{
			pr_Core->VideoManager->DeleteImage(&pr_Image);
		}
	}

	ClearAnimations();

	return true;
}

void CFont::ParseImage()
{

}

bool CFont::Create(const std::string cp_chFileName,const CVector &cFrameSize)
{
    if(pr_Core)
	{
		pr_Image = pr_Core->VideoManager->LoadImage(cp_chFileName);
		pr_Image->SetFrameSize(cFrameSize);
		p_Font->p_FontImage = pr_Image;
		ParseImage();

		return true;
	}

	return false;
}
//TODO FALTA FAZER O PARSE AQUI IGUAL O SFONT
void CFont::Write(const std::string & strText, int x, int y)
{
    if(strText != strTextBuffer)
    {
        strTextBuffer = strText;
        int x,y = 0;
        int charoffset;
        const char *c;
        CFrame srcFrame, dstFrame;

        for(c = strText.c_str(); *c != '\0'; c++)
        {
            charoffset = ((int) (*c - 33)) * 2 + 1;
            // skip spaces and nonprintable characters
            if (*c == ' ' || charoffset < 0 || charoffset > p_Font->MaxPos) {
                x += p_Font->CharPos[2]-p_Font->CharPos[1];
                continue;
            }

            p_fontBuffer->DrawImage(&dstFrame,p_Font->p_FontImage,&srcFrame);
        }
    }
}

void CFont::Draw()
{
	if(pr_Core)
	{
		CVector Pos;

        if(pr_Layer)
        {
            Pos = pr_Layer->GetBackBufferPos(Position,p_fontBuffer->FrameSize);
        }
        else
        {
            Pos = Position;
        }
        Pos.Floor();
        if(bVisible)
        {
            pr_Core->VideoManager->Screen.DrawImage(Pos,p_fontBuffer,0);
        }
	}
}

void CFont::Update(void)
{

	//se existe animação e o índice dela é válido então atualiza a animação corrente
	if((sCurrentAnim >= 0) && (sCurrentAnim < (int)Animations.size()))
	{
		Animations[sCurrentAnim]->Update();
	}

}

void CFont::AddAnimation(int iFPS,bool bRepeat, int iFrameCount,...)
{
    //cria um novo objeto de animação
	CAnimation *p_Animation = new CAnimation();

	//passa os parâmetros para a animação
	p_Animation->pr_Core					= pr_Core;
	p_Animation->bRepeat					= bRepeat;
	p_Animation->SetFrameInterval(iFPS,0);

	va_list marker;
	//inicializa a lista para extrair os quadros da animação (parâmetro "...")
	va_start(marker, iFrameCount);

	//extrai cada quadro da lista e adiciona na animação
	for(int i = 0; i < iFrameCount; i++)
	{
		p_Animation->Frames.push_back(va_arg(marker, int));
	}

	//finaliza a lista
	va_end( marker );

	//adiciona a animação na lista do Font
    Animations.push_back(p_Animation);

}

//----------------------------------------------------------------------------
// Nome: ResetAnimation(void)
// Desc: Reinicia a animação corrente
// Pams: nenhum
//----------------------------------------------------------------------------
void CFont::ResetAnimation(void)
{
	if(sCurrentAnim >= 0 && sCurrentAnim < (int)Animations.size())
	{
		Animations[sCurrentAnim]->Reset();
	}
}

//----------------------------------------------------------------------------
// Nome: SetCurrentAnimation(short sAnim)
// Desc: seta a animação corrente
// Pams: animação
//----------------------------------------------------------------------------
void CFont::SetCurrentAnimation(short sAnim)
{
	if(sAnim != sCurrentAnim)
	{
		sCurrentAnim = sAnim;
		ResetAnimation();
	}
}

//----------------------------------------------------------------------------
// Nome: ClearAnimations(void)
// Desc: Exclui todas as animações do vetor
// Pams: nenhum
//----------------------------------------------------------------------------
void CFont::ClearAnimations(void)
{
	for(int i = (int)Animations.size()-1; i >=0; i--)
	{
		delete Animations[i];
	}

	Animations.clear();
}

//----------------------------------------------------------------------------
// Nome: GetFrame(bool bAddToLayer)
// Desc: Um Frame
//----------------------------------------------------------------------------
CFrame CFont::GetFrame(void)
{
	CFrame Frame;
	Frame.iLeft   = (int)Position.fx;
	Frame.iTop    = (int)Position.fy;
	Frame.iRight  = (int)(Position.fx + pr_Image->FrameSize.fx);
	Frame.iBottom = (int)(Position.fy + pr_Image->FrameSize.fy);

	return Frame;
}
